package com.example.base_model.network.interceptor

import android.Manifest
import android.content.Context
import androidx.annotation.RequiresPermission
import com.blankj.utilcode.util.NetworkUtils
import okhttp3.Cache
import okhttp3.Interceptor
import okhttp3.Response
import java.io.File

/**
 * @Author jiangKunKun
 * @CreateDate 2025/8/6
 * @Description 一个为网络请求提供动态缓存策略的 OkHttp 拦截器。
 * 它的核心功能是根据当前设备的网络连接状态，动态地修改请求的 `Cache-Control` 头，
 * 从而实现两种不同的缓存行为：
 * 1. **有网络时**: 遵循 `max-age` 策略，从服务器获取最新数据或使用指定时间内的缓存。
 * 2. **无网络时**: 遵循 `max-stale` 策略，强制使用缓存，即使它已经过期。
 * @SpittingGrooves
 */
class CacheInterceptor : Interceptor {
    /**
     * 定义了针对不同 API 路径的缓存策略。
     * - **Key (String)**: API 的 URL 路径前缀。
     * - **Value (CacheStrategy)**: 对应的缓存策略，包含 `maxAge` 和 `maxStale`。
     * 通过在这里添加条目，可以为特定的接口配置自定义的缓存时间。
     */
    private val cacheStrategies = mapOf<String, CacheStrategy>(
//        // 示例：物联网认证接口，数据较稳定，缓存 10 分钟
//        "/iot/collect/v3/auth" to CacheStrategy(
//            maxAge = 60 * 10,           // 有网：缓存 10 分钟
//            maxStale = 60 * 60 * 24     // 无网：最多用 24 小时前的缓存
//        ),
//        // 示例：用户信息，缓存 1 小时
//        "/user/profile" to CacheStrategy(
//            maxAge = 60 * 60,           // 1 小时
//            maxStale = 60 * 60 * 24     // 最多用 24 小时前的数据
//        ),
//        // 示例：新闻列表，更新快，只缓存 30 秒
//        "/news/list" to CacheStrategy(
//            maxAge = 60 * 30,           // 30 秒
//            maxStale = 60 * 60          // 最多用 1 小时前的缓存
//        ),
//        // 示例：系统配置，几乎不变，缓存 24 小时
//        "/config/app" to CacheStrategy(
//            maxAge = 60 * 60 * 24,      // 24 小时
//            maxStale = 60 * 60 * 24 * 7 // 最多用 7 天前的缓存
//        ),
//        // 示例：头像等静态资源，缓存 1 小时，离线可用 30 天
//        "/avatar/" to CacheStrategy(
//            maxAge = 60 * 60,           // 1 小时
//            maxStale = 60 * 60 * 24 * 30 // 30 天
//        )
    )

    @RequiresPermission(Manifest.permission.INTERNET)
    override fun intercept(chain: Interceptor.Chain): Response {
        var request = chain.request()
        // 1. 根据请求的 URL，从 `cacheStrategies` 中查找匹配的缓存策略。
        //    如果找不到匹配的策略，则使用一个默认的策略（有网缓存5秒，无网使用7天内的旧缓存）。
        val strategy = findMatchingStrategy(request.url.toString()) ?: CacheStrategy(5, 60 * 60 * 24 * 7)

        // 2. 检查当前设备是否有可用的网络连接。
        if (NetworkUtils.isAvailable()) {
            // 3a. 有网络的情况：
            // 设置 `Cache-Control` 头为 `max-age`。
            // 这告诉 OkHttp，在 `max-age` 指定的秒数内，可以直接使用缓存的响应，无需发起网络请求。
            // 超过这个时间后，OkHttp 会重新向服务器验证缓存是否仍然有效。
            val cacheControl = "max-age=${strategy.maxAge}"
            request = request.newBuilder()
                .header("Cache-Control", cacheControl)
                .build()
        } else {
            // 3b. 无网络的情况：
            // 设置 `Cache-Control` 头为 `only-if-cached` 和 `max-stale`。
            // - `only-if-cached`: 强制 OkHttp 只从缓存中读取响应，绝不发起网络请求。
            // - `max-stale`: 允许 OkHttp 使用已过期的缓存数据，只要它的过期时间没有超过 `max-stale` 指定的秒数。
            val cacheControl = "only-if-cached, max-stale=${strategy.maxStale}"
            request = request.newBuilder()
                .header("Cache-Control", cacheControl)
                .build()
        }
        // 4. 使用修改后的请求继续执行拦截器链。
        return chain.proceed(request)
    }

    /**
     * 根据给定的 URL 字符串，查找第一个匹配的缓存策略。
     * 匹配逻辑是检查 URL 是否包含 `cacheStrategies` map 中的某个键（路径前缀）。
     *
     * @param url 请求的完整 URL。
     * @return 找到的 [CacheStrategy]，如果没找到则返回 `null`。
     */
    private fun findMatchingStrategy(url: String): CacheStrategy? {
        return cacheStrategies.entries
            .firstOrNull { url.contains(it.key) }
            ?.value
    }

    /**
     * 数据类，用于封装一个具体的缓存策略。
     *
     * @property maxAge 有网络时，缓存被视为“新鲜”的最长时间（单位：秒）。在此期间，请求将直接从缓存返回。
     * @property maxStale 无网络时，允许使用已过期缓存的最大容忍时间（单位：秒）。
     */
    data class CacheStrategy(
        val maxAge: Int,
        val maxStale: Int
    )

    /**
     * 伴生对象，提供用于创建 OkHttp [Cache] 实例的静态方法。
     */
    companion object {
        /**
         * 创建一个用于 HTTP 缓存的 OkHttp [Cache] 对象。
         *
         * @param context Application 上下文，用于获取缓存目录。
         * @return 配置好目录和大小的 [Cache] 实例。
         */
        fun createHttpCache(context: Context): Cache {
            // 1. 定义缓存文件的存储目录。
            val httpCacheDirectory = File(context.cacheDir, "http_cache")
            // 2. 定义缓存的最大存储空间（这里是 50 MB）。
            val cacheSize = 50L * 1024 * 1024 // 50 MB
            // 3. 创建并返回 Cache 实例。
            return Cache(httpCacheDirectory, cacheSize)
        }
    }
}
